#pragma once

#include <iostream>
#include <sys/select.h>
#include <string>
#include <functional>
#include<poll.h>
#include "Sock.hpp"

using namespace std;

namespace Poll_sv
{
    static const int defaultport = 8080;         // 默认端口号
    static const int defaultfd = -1;             // 默认套接字标志
    static  const int fdnum=2048;//设置文件描述符的数量
    using func_t = function<string(const string &)>;
    class PollServer
    {
    public:
        PollServer(func_t f, int port = defaultport) : _func(f), _port(port), _listensock(-1),_rfds(nullptr)
        {
        }
        void initServer()
        {
            // 获取套接字
            _listensock = Sock::Socket();
            cout << "Sock success" << endl;
            // 绑定网络信息
            Sock::Bind(_listensock, _port);
            cout << "Bind success" << endl;
            // 把套接字设置为监听状态
            Sock::Listen(_listensock);
            cout << "Listen success" << endl;

                _rfds=new struct pollfd[fdnum];//指针指向一个成员是poll结构体的数组
                for(int i=0;i<fdnum;i++)
                {
                    _rfds[i].fd=defaultfd;
                    _rfds[i].events=0;
                    _rfds[i].revents=0;
                }
                _rfds[0].fd=_listensock;
                _rfds[0].events=POLLIN;
                cout << "initServer" << endl;
        }
        void Print()
        {
            cout << "now using socket: ";
            for (int i = 0; i < fdnum; i++)
            {
                if(_rfds[i].fd!=defaultfd)
                cout<<_rfds[i].fd<<" ";//打印正在使用的fd
            }
            cout << endl;
        }
        void Accpter(int lsock)
        {
            logMessage(DEBUG, "Accepter begin");
            string clientip;
            uint16_t clientport = 0;
            int sock = Sock::Accpet(lsock, &clientip, &clientport); // 若成功返回，返回一个用于通信的套接字
            if (sock < 0)
                return;
            logMessage(NORMAL, "accept success [%s:%d]", clientip.c_str(), clientport);
            int i=0;
            for(;i<fdnum;i++)
            {
                if(_rfds[i].fd!=defaultfd)//这里是找到默认的位置，给后续需要使用的文件描述符用，因此是跳过已经被使用的位置
                continue;
                else break;
            }
            if(i==fdnum)
            {
                close(sock);
                logMessage(WARNING,"fd full,please wait");
            }else
            {
                _rfds[i].fd=sock;
                _rfds[i].events=POLLIN;
                _rfds[i].revents=0;
                logMessage(NORMAL,"sock has set in rfds");
            }
            Print();
            logMessage(DEBUG, "Accepter end");
        }

        void Recver(int pos)
        {
            logMessage(DEBUG, "Recver begin");
            char buffer[1024];
            ssize_t s = recv(_rfds[pos].fd, buffer, sizeof(buffer) - 1, 0);
            if (s > 0)
            {
                buffer[s] = 0;
                cout << "client# " << buffer << endl;
            }
            else if (s == 0)
            {
                close(_rfds[pos].fd);               // 关闭该套接字，关闭通信通道
                _rfds[pos].fd = defaultfd; // 将数组中的该套接字清除
                logMessage(NORMAL, "client quit");
                return;
            }
            else
            {
                close(_rfds[pos].fd);
               _rfds[pos].fd = defaultfd; // 将数组中的该套接字清除
                logMessage(ERROR, "recv error");
                return;
            }
            // 将客户端发来的数据原样写回去
            string resp = _func(buffer);

            write(_rfds[pos].fd, resp.c_str(), resp.size()); // 写回去
            logMessage(DEBUG, "Recever end");
        }
        void Handlerop()
        {
            for (int i = 0; i < fdnum; i++)
            {
                if (_rfds[i].fd == defaultfd)//fd没有被设置则跳过
                    continue;
                
                if(!(_rfds[i].events&POLLIN)) continue;//结构体不是被指定标志位POLLIN设置过则跳过

                if (_rfds[i].fd==_listensock&&_rfds[i].revents&POLLIN)
                // 此时i对应的数组位置是拿到连接的文件描述符，意味着在底层连接已经拿到，等待上层提取
                {
                    Accpter(_listensock);
                }
                else if (_rfds[i].revents&POLLIN) // 此时存在数组内的对应套接字都是底层读资源就绪
                {
                    Recver(i);
                }
                else
                {}
            }
        }
        void Start()
        {
            int timeout=-1;
            for(;;)
            {
                cout<<"poll ready"<<endl;
                int n=poll(_rfds,fdnum,timeout);
                cout<<"poll finished"<<endl;
                switch(n)
                {
                case 0:
                logMessage(NORMAL,"timeout...");
                break;
                case -1:
                logMessage(WARNING,"poll error");
                break;
                default:
                logMessage(NORMAL,"poll success");
                Handlerop();
                break;
                }
            }
        }

        ~PollServer()
        {
            if (_listensock < 0) // 为什么是小于0？
                close(_listensock);
            if(_rfds!=nullptr)
            delete[]_rfds;
        }

    private:
        int _port;
        int _listensock;
        struct pollfd* _rfds;//指向poll结构体的指针
        func_t _func;
    };
}